package com.mlx.meng.verify;

import com.mlx.meng.tool.DataPermissionException;
import com.mlx.meng.tool.DataPermissionUtil;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

/**
 * 列权限验证器
 */
public class DataPermissionColumnVerification {

    private HashMap<String, HashSet<String>> columnPermission;

    public DataPermissionColumnVerification(){
        this.columnPermission = new HashMap<>();
    }

    private HashSet<String> get(String tableName){
        HashSet<String> tableColumnPermission = columnPermission.get(tableName);
        if (DataPermissionUtil.isEmpty(tableColumnPermission)){
            return new HashSet<>();
        }
        return tableColumnPermission;
    }


    private HashSet<String> get(String[] foreignKeys){
        HashSet<String> fieldPermission =new HashSet<>();
        int length = foreignKeys.length;
        if (length > 0){
            for (int i = 0 ; i < length ; i++){
                String foreignKey = foreignKeys[i];
                if (!(DataPermissionUtil.checkForeignKeyFormat(foreignKey))){
                    throw new DataPermissionException(String.format("检查DataAuthor注解的foreignKeys外键数组第【%d】个元素发不是合法的外键映射表达式", i + 1));
                }
                String[] split = foreignKey.split(":");
                HashSet<String> tablePermissions = get(split[1]);
                if (tablePermissions.isEmpty()){
                    throw new DataPermissionException(String.format("检查DataAuthor注解的foreignKeys外键数组第【%d】个元素表名【%s】不存在权限字段", i + 1, split[1]));
                }
                if (!(tablePermissions.contains(split[2]))){
                    throw new DataPermissionException(String.format("检查DataAuthor注解的foreignKeys外键数组第【%d】个元素表名【%s】不存在字段名【%s】的权限字段", i + 1, split[1], split[2]));
                }
                fieldPermission.add(split[0]);
            }
        }
        return fieldPermission;
    }

    public void put(String tableName, String fieldName){
        if (columnPermission.containsKey(tableName)){
            HashSet<String> tableColumnPermission = columnPermission.get(tableName);
            tableColumnPermission.add(fieldName);
        }else {
            HashSet<String> tableColumnPermission = new HashSet<>();
            tableColumnPermission.add(fieldName);
            columnPermission.put(tableName, tableColumnPermission);
        }
    }

    public DataPermissionColumnEntityVerification buildDataPermissionColumnEntity(String tableName, String[] foreignKeys){
        return new DataPermissionColumnEntityVerification(tableName, foreignKeys);
    }

    /**
     * 列数据权限的实体验证器
     */
    public class DataPermissionColumnEntityVerification {

        private HashSet<String> entityColumnPermission;

        private DataPermissionColumnEntityVerification(String tableName, String[] foreignKeys){
            entityColumnPermission = new HashSet<>();
            HashSet<String> tableColumnPermission = get(tableName);
            HashSet<String> fieldPermission = get(foreignKeys);
            entityColumnPermission.addAll(tableColumnPermission);
            entityColumnPermission.addAll(fieldPermission);
        }

        public void columnPermissionFilter(Object data, Map<String, Field> classFieldMap) throws Exception{
            if (DataPermissionUtil.isEmpty(data)){
                return;
            }
            Set<String> keySet = classFieldMap.keySet();
            for(String k : keySet){
                if (!(entityColumnPermission.contains(k))){
                    Field field = classFieldMap.get(k);
                    field.set(data, null);
                }
            }
        }

        public void columnPermissionFilter(Object data, Method setMethod, int fieldTypeIndex, Method getAllFieldMethod) throws Exception{
            if (DataPermissionUtil.isEmpty(data)){
                return;
            }


            Collection<?> allField = (Collection<?>) getAllFieldMethod.invoke(data);

            for(Object k : allField){
                if (!(entityColumnPermission.contains(k.toString()))){
                    if (fieldTypeIndex == 0){
                        setMethod.invoke(data, k, null);
                    }else {
                        setMethod.invoke(data,  null, k);
                    }
                }
            }
        }

        public HashSet<String> getEntityColumnPermission() {
            return entityColumnPermission;
        }

        public boolean isNotExistDataPermission(){
            return DataPermissionUtil.isEmpty(entityColumnPermission);
        }
    }
}
